package cc.chinagps.gateway.unit.eg.upload.cmds;

import cc.chinagps.gateway.buff.InnerDataBuff;
import cc.chinagps.gateway.client.TransferDeviceManager;
import cc.chinagps.gateway.log.LogManager;
import cc.chinagps.gateway.memcache.MemcacheManager;
import cc.chinagps.gateway.unit.UnitServer;
import cc.chinagps.gateway.unit.UnitSocketSession;
import cc.chinagps.gateway.unit.beans.Loginout;
import cc.chinagps.gateway.unit.beans.UnitInfo;
import cc.chinagps.gateway.unit.common.UnitCommon;
import cc.chinagps.gateway.unit.common.UploadUtil;
import cc.chinagps.gateway.unit.eg.define.EGDefines;
import cc.chinagps.gateway.unit.eg.pkg.EGHead;
import cc.chinagps.gateway.unit.eg.pkg.EGPackage;
import cc.chinagps.gateway.unit.eg.upload.DeviceInfoManager;
import cc.chinagps.gateway.unit.eg.upload.bean.EGDevice;
import cc.chinagps.gateway.unit.eg.util.EGTimeFormatUtil;
import cc.chinagps.gateway.unit.eg.util.EGUploadUtil;
import cc.chinagps.gateway.util.Constants;
import cc.chinagps.gateway.util.HexUtil;
import cc.chinagps.gateway.util.SingletonFactory;
import org.apache.log4j.Logger;
import org.seg.lib.util.SegPackageUtil;
import org.seg.lib.util.Util;

import java.util.Date;

public class Cmd01 implements UploadHandler {
    private Logger logger_debug = Logger.getLogger(LogManager.LOGGER_NAME_DEBUG);

    private void loginAck(short serialNo, byte result, EGPackage pkg, UnitSocketSession session) throws Exception {
        byte[] resData = new byte[3];
        System.arraycopy(Util.getShortByte(serialNo), 0, resData, 0, 2);
        resData[2] = result;
        EGUploadUtil.msgAck(session, pkg, resData);
    }

    @Override
    public boolean handlerPackage(EGPackage pkg, UnitServer server, UnitSocketSession session) throws Exception {
        logger_debug.debug("[EG]recev login data:" + HexUtil.byteToHexStr(pkg.getSource()) + ";session:" + session);
        EGHead head = pkg.getHead();
        String vin = head.getVin();
        String deviceId = null;
        String initParam = null;
        String swVersion = null;
        int pos = 0;
        byte data[] = pkg.getData();
        String collectTime = EGTimeFormatUtil.getDateTime(data, pos, 6);
        pos += 6;
        short serialNo = Util.getShort(data, pos);
        pos += 2;
        String iccid = new String(data, pos, 20, EGDefines.CHARSET);
        pos += 20;
        if (pos < data.length) {
            initParam = new String(data, pos, 3, EGDefines.CHARSET);
            pos += 3;
            swVersion = new String(data, pos, 8, EGDefines.CHARSET);
            pos += 8;
            deviceId = new String(data, pos, data.length - pos, EGDefines.CHARSET);
        }
        EGDevice egDevice;
        if (deviceId == null) {
            egDevice = SingletonFactory.getInstance(DeviceInfoManager.class).getDeviceByIccid(iccid);
        } else {
            egDevice = SingletonFactory.getInstance(DeviceInfoManager.class).getDeviceById(deviceId);
        }

        if (egDevice == null || egDevice.getDeviceId() == null) {
            loginAck(serialNo, (byte) 2, pkg, session);
            if (logger_debug.isDebugEnabled()) {
                StringBuilder logInfo = new StringBuilder();
                logInfo.append("[EG]unit login failed, iccid:").append(iccid);
                logInfo.append(", collectTime:").append(collectTime);
                logInfo.append(", vin:").append(vin);
                logInfo.append(", initParam:").append(initParam);
                logInfo.append(", swVersion:").append(swVersion);
                logInfo.append(", deviceId:").append(deviceId);
                logInfo.append(", source code:").append(HexUtil.byteToHexStr(pkg.getSource()));
                logger_debug.debug(logInfo.toString());
            }
            return true;
        }

        egDevice.setIccid(iccid);
        egDevice.setConfParam(initParam);
        egDevice.setSwVersion(swVersion);
        egDevice.setSwVersionNO(head.getSoftwareVersion() + "");
        SingletonFactory.getInstance(DeviceInfoManager.class).addVersion(egDevice);

        String callLetter = egDevice.getDeviceId();
        UnitSocketSession existSession = server.searchUnitByCallLetter(callLetter);
        if (existSession != null && existSession != session) {
            logger_debug.debug("[EG][cmd01]existSession:" + existSession + " is not same as the current session :"
                    + session + " then close the existed!");
            existSession.close();
        }

        boolean isNew;
        if (session.getUnitInfo() != null) {
            isNew = false;
            String oldCall = session.getUnitInfo().getCallLetter();

            session.getUnitInfo().setCallLetter(callLetter);
            session.getUnitInfo().setIccid(iccid);
            session.getUnitInfo().setVin(vin);
            session.getUnitInfo().setSoftwareVersion(head.getSoftwareVersion());
            session.getUnitInfo().setEncryption(head.getEncryption());
            server.getSessionManager().removeCallSession(oldCall);
            server.getSessionManager().addCallSession(callLetter, session);
        } else {
            isNew = true;
            UnitInfo unitInfo = new UnitInfo();
            unitInfo.setCallLetter(callLetter);
            unitInfo.setVin(vin);
            unitInfo.setIccid(iccid);
            unitInfo.setSoftwareVersion(head.getSoftwareVersion());
            unitInfo.setEncryption(head.getEncryption());
            session.setUnitInfo(unitInfo);

            session.setLoginTime(EGTimeFormatUtil.parseGMT8("20" + collectTime).getTime() + 1);
            server.getSessionManager().addCallSession(callLetter, session);
        }

        loginAck(serialNo, (byte) 1, pkg, session);

        UnitCommon.sendUploadTrace(pkg.getSource(), server, session);

        Loginout loginout = new Loginout();
        loginout.setIsLogin(isNew ? Loginout.LOGIN : Loginout.CHANGE_LOGIN);
        loginout.setLoginTime(session.getLoginTime());
        loginout.setCallLetter(callLetter);
        UploadUtil.handleLoginout(server, session, loginout);

        byte[] bodyData = InnerDataBuff.Unit.newBuilder().setCallLetter(callLetter).build().toByteArray();
        server.getSeatServer().getTCPServer().broadcastPackage(false, false, false,
                Constants.INNER_CMD_ID_VEHICLE_ONLINE_NOTIFY, SegPackageUtil.getSerialNumber(), bodyData,
                UnitCommon.unitLoginChangeFilter);

        if (!Constants.IS_UPDATE_SERVER) {
            long now = System.currentTimeMillis();
            Date expDate = new Date(now + MemcacheManager.ROUTING_EXPIRED);
            boolean success = MemcacheManager.getMemcachedClient().set(MemcacheManager.ROUTING_KEY_HEAD + callLetter,
                    Constants.SYSTEM_ID, expDate);
            if (success) {
                session.getUnitInfo().setLastUpdateRouteTime(now);
            }
        }

        if (logger_debug.isDebugEnabled()) {
            StringBuilder logInfo = new StringBuilder();
            logInfo.append("[EG]Unit login, callLetter:").append(callLetter);
            logInfo.append(", iccid:").append(iccid);
            logInfo.append(", collectTime:").append(collectTime);
            logInfo.append(", vin:").append(vin);
            logInfo.append(", initParam:").append(initParam);
            logInfo.append(", swVersion:").append(swVersion);
            logInfo.append(", deviceId:").append(deviceId);
            logInfo.append(", Source code:").append(HexUtil.byteToHexStr(pkg.getSource()));
            logger_debug.debug(logInfo.toString());
        }
        TransferDeviceManager.instance.clientConnect(callLetter, pkg);
        return true;
    }

}
